/**
* Copyright (c) 2012-2013 Nokia Corporation. All rights reserved.
* Nokia and Nokia Connecting People are registered trademarks of Nokia Corporation. 
* Oracle and Java are trademarks or registered trademarks of Oracle and/or its
* affiliates. Other product and company names mentioned herein may be trademarks
* or trade names of their respective owners. 
* See LICENSE.TXT for license information.
*/
package com.nokia.example.racer.helpers;

import java.io.IOException;
import javax.microedition.media.Manager;
import javax.microedition.media.MediaException;
import javax.microedition.media.Player;
import javax.microedition.media.PlayerListener;
import javax.microedition.media.control.RateControl;
import java.io.InputStream;
import java.util.Timer;
import java.util.TimerTask;

/*
 * Handles the car engine sound using Player and RateControl.
 * @see javax.microedition.media.Player
 * @see javax.microedition.media.control.RateControl
 */
public class Engine
    implements PlayerListener {

    private Player player;
    private RateControl rateControl;
    private int throttle;
    private Timer timer;
    private TimerTask accelerate;
    private TimerTask decelerate;

    public Engine() {
        initPlayer();
    }

    private void initPlayer() {
        try {
            /*
             * initialize sound player
             */
            InputStream is = this.getClass().getResourceAsStream("/engine.wav");
            player = Manager.createPlayer(is, "audio/wav");
            player.realize();
            player.prefetch();

            /*
             * init playback rate controller
             */
            rateControl = (RateControl) player.getControl("RateControl");
            throttle = rateControl.getMinRate();
            rateControl.setRate(throttle);
            
            /*
             * loop forever
             */
            player.setLoopCount(-1);
            player.addPlayerListener(this);
        }
        catch (IOException ioe) {
            // Nothing to do here.
        }
        catch (MediaException me) {
            // Nothing to do here.
        }
    }

    /**
     * Turns engine on. Starts playing engine sound.
     */
    public void on() {
        try {
            player.start();
        }
        catch (MediaException me) {
            // Nothing to do here.
        }
    }

    /**
     * Turns engine off. Stops playing engine sound.
     */
    public void off() {
        try {
            player.stop();
        }
        catch (MediaException me) {
            // Nothing to do here.
        }
    }

    /**
     * Makes the engine to accelerate, increases engine sound rate
     */
    public void accelerate() {
        resetTimer();
        accelerate = new TimerTask() {

            public void run() {
                /*
                 * set playback rate depending on throttle
                 */
                throttle += 4000;
                if (throttle < rateControl.getMaxRate()) {
                    rateControl.setRate(throttle);
                }
                else {
                    throttle = rateControl.getMaxRate();
                    rateControl.setRate(throttle);
                    this.cancel();
                }
            }
        };
        timer.schedule(accelerate, 0, 40);
    }

    /**
     * Makes the engine to decelerate, decreases engine sound rate
     */
    public void decelerate() {
        resetTimer();
        decelerate = new TimerTask() {

            public void run() {
                /*
                 * set playback rate depending on throttle
                 */
                throttle -= 8000;
                if (throttle > rateControl.getMinRate()) {
                    rateControl.setRate(throttle);
                }
                else {
                    throttle = rateControl.getMinRate();
                    rateControl.setRate(throttle);
                    this.cancel();
                }
            }
        };
        timer.schedule(decelerate, 0, 40);

    }

    /**
     * A method that must be implemented by PlayerListener.
     * @see javax.microedition.media.PlayerListener#playerUpdate(javax.microedition.media.Player, java.lang.String, java.lang.Object)
     * 
     * @param player Media player
     * @param event Media event
     * @param eventData Data related to the media event
     */
    public void playerUpdate(Player player, String event, Object eventData) {
        if (event.equals(PlayerListener.END_OF_MEDIA)) {
            rateControl.setRate(throttle);
        }
    }

    /**
     * Resets the timer if it exists
     */
    private void resetTimer() {
        if (timer != null) {
            try {
                timer.cancel();
            }
            catch (Exception e) {
                // Nothing to do here.
            }
        }
        timer = new Timer();
    }
}
